#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

struct mymsgbuf {
	long mtype;
	char mtext[80];
};

void send_message(int qid, struct mymsgbuf *qbuf, long type, char *text) {
	printf("sending a message...\n");
	qbuf->mtype = type;
	strcpy(qbuf->mtext, text);

	if ((msgsnd(qid, (struct msgbuf*)qbuf, strlen(qbuf->mtext)+1, 0)) == -1) {
		printf("msgsnd error: %s\n", strerror(errno));
		return;
	}
}

void read_message(int qid, struct mymsgbuf *qbuf, long type) {
	printf("reading a message...\n");
	qbuf->mtype = type;
	msgrcv(qid, (struct mymsgbuf *)qbuf, 80, type, 0);

	printf("Type: %ld Text: %s\n", qbuf->mtype, qbuf->mtext);
}

void remove_queue(int qid) {
	msgctl(qid, IPC_RMID, 0);
}

void change_queue_mode(int qid, char* mode) {
	struct msqid_ds myqueue_ds;
	msgctl(qid, IPC_STAT, &myqueue_ds);

	sscanf(mode, "%ho", &myqueue_ds.msg_perm.mode);
	msgctl(qid, IPC_SET, &myqueue_ds);
}

void usage(void) {
	printf("msgqueue tool\n");
	printf("15-12 (s)end \n");
	printf("15-12 (r)ecv \n");
	printf("15-12 (d)elete\n");
	printf("15-12 (m)ode\n");
}

int main(int argc, char* argv[]) {
	key_t key;
	int qid;
	struct mymsgbuf qbuf;

	if (1 == argc) {
		usage();
		return;
	}

	key = ftok(".", 'm');

	if ((qid=msgget(key, IPC_CREAT|0660)) == -1) {
		printf("msgget error: %s\n", strerror(errno));
		return -1;
	}
	
	switch (tolower(argv[1][0])) {
		case 's':
			send_message(qid, (struct mymsgbuf*)&qbuf, atol(argv[2]), argv[3]);
			break;
		case 'r':
			read_message(qid, (struct mymsgbuf*)&qbuf, atol(argv[2]));
			break;
		case 'm':
			change_queue_mode(qid, argv[2]);
		case 'd':
			remove_queue(qid);
			break;
		default:
			usage();
	}
	
	return 0;
}
